// 实现这个项目的构建任务
// 导入 gulp ，css|js|html转换流，gulp 模块自动导入模块
const { src, dest, series, parallel, watch } = require('gulp')
const del = require('del')
const browserSync = require('browser-sync')
const nvpConfig = require('./nvpConfig.js')

const loadPlugin = require('gulp-load-plugins')
const bs = browserSync.create()

const data = nvpConfig.data

const plugins = loadPlugin()
const config = {
  build: nvpConfig.build
}

const clean = () => del([config.build.dist, config.build.temp])

const style = () => {
  return src(config.build.path.styles, { base: config.build.base, cwd: config.build.base })
    .pipe(plugins.sass())
    .pipe(dest(config.build.temp))
}

const script = () => {
  return src(config.build.path.script, { base: config.build.base, cwd: config.build.base })
    .pipe( plugins.babel({ presets: ['@babel/preset-env'] }) )
    .pipe(dest(config.build.temp))
}

// swig 模板引擎转换 html 文件流
const swig = () => {
  return src(config.build.path.html, { base: config.build.base, cwd: config.build.base })
    .pipe( plugins.swig({ data }) )
    .pipe(dest(config.build.temp))
}

const image = () => {
  return src(config.build.path.img, { base: config.build.base, cwd: config.build.base })
    .pipe( plugins.imagemin() )
    .pipe(dest(config.build.dist))
}

const font = () => {
  return src(config.build.path.font, { base: config.build.base, cwd: config.build.base })
    .pipe( plugins.imagemin() )
    .pipe(dest(config.build.dist))
}

const public = () => {
  return src('**', { base: config.build.public, cwd: config.build.public })
    .pipe(dest(config.build.dist))
}

// 处理 compile 构建的文件
// 加载页面中构建注释中导入的文件，并导出到构建注释中指定的文件内
// 可以用来加载引入的 node_modules 文件，并打包到指定目录中
const useref = () => {
  return src('**/*.html', { base: config.build.temp, cwd: config.build.temp })
    .pipe(plugins.useref({ searchPath: [ config.build.temp, '.'] }))
    .pipe(plugins.if(/\.js$/, plugins.uglify()))
    .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
    .pipe(plugins.if(/\.html$/, plugins.htmlmin({
      collapseWhitespace: true,
      minifyCSS: true,
      minifyJS: true,
    })))
    .pipe(dest(config.build.dist))
}

// 构建页面的主文件，主要是html，js和css
const compile = parallel(style, script, swig)

const build = series(clean, compile, parallel(useref, image, font, public))

/**
 * @author nvp
 * 开启服务器和并对页面资源进行监听，在页面资源变更时，更新对应处理任务
 * img, 字体 等静态在生产环境中只需要做一些压缩工作，因此没必要在开发阶段进行压缩
 * 开发阶段将直接使用 base 下的源资源
*/
const servers = () => {
  // 监听源文件的修改，并执行对应的编译任务
  watch(config.build.path.styles, { cwd: config.build.base }, style)
  watch(config.build.path.script, { cwd: config.build.base }, script)
  watch(config.build.path.html, { cwd: config.build.base }, swig)

  // 监听静态资源的变更，
  // 变更时只需要直接更新下页面
  watch(
    [
      config.build.path.img,
      config.build.path.font,
    ], 
    { cwd: config.build.base }, 
    bs.reload()
  )
  watch('**', { cwd: config.build.public }, bs.reload())
  
  // 初始化服务器
  bs.init({
    port: 8080,
    files: config.build.temp,
    server: {
      baseDir: [config.build.temp, config.build.base, config.build.public],
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}

// 开发环境，创建服务器运行代码
const serve = series(clean, compile, servers)

module.exports = {
  clean,
  build,
  serve,
}